/*
 * This file is part of aion-engine <aion-engine.com>
 *
 * aion-engine is private software: you can redistribute it and or modify
 * it under the terms of the GNU Lesser Public License as published by
 * the Private Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * aion-engine is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser Public License
 * along with aion-engine.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.aionengine.gameserver.questEngine.handlers.template;

import com.aionengine.gameserver.model.DialogAction;
import com.aionengine.gameserver.model.gameobjects.player.Player;
import com.aionengine.gameserver.model.rift.RiftLocation;
import com.aionengine.gameserver.model.vortex.VortexLocation;
import com.aionengine.gameserver.questEngine.handlers.QuestHandler;
import com.aionengine.gameserver.questEngine.model.QuestEnv;
import com.aionengine.gameserver.questEngine.model.QuestState;
import com.aionengine.gameserver.questEngine.model.QuestStatus;
import com.aionengine.gameserver.services.QuestService;
import com.aionengine.gameserver.services.RiftService;
import com.aionengine.gameserver.services.VortexService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * Standard xml-based handling for the DAILY quests with onKillInZone events
 *
 * @author vlog, reworked bobobear
 */
public class KillInWorld extends QuestHandler {

    private static final Logger log = LoggerFactory.getLogger(KillInWorld.class);

    private final Set<Integer> startNpcs = new HashSet<Integer>();
    private final Set<Integer> endNpcs = new HashSet<Integer>();
    private final Set<Integer> worldIds = new HashSet<Integer>();
    private final int killAmount;
    private final int invasionWorldId;

    public KillInWorld(int questId, List<Integer> endNpcIds, List<Integer> startNpcIds, List<Integer> worldIds, int killAmount, int invasionWorld) {
        super(questId);
        if (startNpcIds != null) {
            this.startNpcs.addAll(startNpcIds);
            this.startNpcs.remove(0);
        }
        if (endNpcIds == null) {
            this.endNpcs.addAll(startNpcs);
        } else {
            this.endNpcs.addAll(endNpcIds);
            this.endNpcs.remove(0);
        }
        this.worldIds.addAll(worldIds);
        this.worldIds.remove(0);
        this.killAmount = killAmount;
        this.invasionWorldId = invasionWorld;
    }

    @Override
    protected void onWorkItemsLoaded() {
        if (workItems == null)
            return;
        if (workItems.size() > 0) {
            log.warn("Q{} (KillInWorld) has a work item.", questId);
        }
    }

    @Override
    public void register() {
        Iterator<Integer> iterator = startNpcs.iterator();
        while (iterator.hasNext()) {
            int startNpc = iterator.next();
            qe.registerQuestNpc(startNpc).addOnQuestStart(getQuestId());
            qe.registerQuestNpc(startNpc).addOnTalkEvent(getQuestId());
        }
        iterator = endNpcs.iterator();
        while (iterator.hasNext()) {
            int endNpc = iterator.next();
            qe.registerQuestNpc(endNpc).addOnTalkEvent(getQuestId());
        }
        iterator = worldIds.iterator();
        while (iterator.hasNext()) {
            int worldId = iterator.next();
            qe.registerOnKillInWorld(worldId, questId);
        }
        if (invasionWorldId != 0)
            qe.registerOnEnterWorld(questId);
    }

    @Override
    public boolean onDialogEvent(QuestEnv env) {
        Player player = env.getPlayer();
        QuestState qs = player.getQuestStateList().getQuestState(questId);
        int targetId = env.getTargetId();
        DialogAction dialog = env.getDialog();
        if (qs == null || qs.getStatus() == QuestStatus.NONE || qs.canRepeat()) {
            if (startNpcs.isEmpty() || startNpcs.contains(targetId)) {
                switch (dialog) {
                    case QUEST_SELECT: {
                        return sendQuestDialog(env, 4762);
                    }
                    case QUEST_ACCEPT_1: {
                        return sendQuestStartDialog(env);
                    }
                    default: {
                        return sendQuestStartDialog(env);
                    }
                }
            }
        } else if (qs != null && qs.getStatus() == QuestStatus.REWARD) {
            if (endNpcs.contains(targetId)) {
                return sendQuestEndDialog(env);
            }
        }
        return false;
    }

    @Override
    public boolean onEnterWorldEvent(QuestEnv env) {
        Player player = env.getPlayer();
        QuestState qs = player.getQuestStateList().getQuestState(questId);
        VortexLocation vortexLoc = VortexService.getInstance().getLocationByWorld(invasionWorldId);
        if (player.getWorldId() == invasionWorldId) {
            if ((qs == null || qs.getStatus() == QuestStatus.NONE || qs.canRepeat())) {
                if ((vortexLoc != null && vortexLoc.isActive()) || (searchOpenRift()))
                    return QuestService.startQuest(env);
            }
        }
        return false;
    }


    private boolean searchOpenRift() {
        for (RiftLocation loc : RiftService.getInstance().getRiftLocations().values()) {
            if (loc.getWorldId() == invasionWorldId && loc.isOpened()) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean onKillInWorldEvent(QuestEnv env) {
        return defaultOnKillRankedEvent(env, 0, killAmount, true); // reward
    }

    @Override
    public HashSet<Integer> getNpcIds() {
        if (constantSpawns == null) {
            constantSpawns = new HashSet<>();
            if (startNpcs != null)
                constantSpawns.addAll(startNpcs);
            if (endNpcs != null)
                constantSpawns.addAll(endNpcs);
        }
        return constantSpawns;
    }
}
